/**
 * @author t.murdock
 *
 * @class Ext.ux.form.HexField
 * @extends Ext.form.TextField
 * 
 * Will only allow Hex values
 */

Ext.namespace("Ext.ux.form");

Ext.ux.form.HexField = Ext.extend(Ext.form.TextField,  {
	initEvents : function(){
		Ext.ux.form.HexField.superclass.initEvents.call(this);
		
		var keyPress = function(e){
			var k = e.getKey();
			
			if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
				return;
			}
			
			// allowed text characters
			var allowed = '0123456789abcdefABCDEF';
			
			// get selected text length
			var selection = new Ext.ux.form.HexField.Selection( document.getElementById(this.id) );
			var s = selection.create();
			var selLength = s.end - s.start;
			
			// get text character keyed in
			var c = e.getCharCode();
			var c = String.fromCharCode(c);
			var value = c + this.getValue();
			
			if(allowed.indexOf(c) === -1 || (value.length > 6 && selLength === 0) ){
				e.stopEvent();
			}
		};
		this.el.on("keypress", keyPress, this);
	}
	
	, validateValue : function(value){
		if(!Ext.ux.form.HexField.superclass.validateValue.call(this, value)){
			return false;
		}
		if(!/^[0-9a-fA-F]{6}$/.test(value)){
			return false;
		}
		return true;
    }
});
Ext.reg('hexfield', Ext.ux.form.HexField);

Ext.ux.form.HexField.Selection = function(textareaElement) {
    this.element = textareaElement;
};

Ext.ux.form.HexField.Selection.prototype.create = function() {
    if (document.selection != null && this.element.selectionStart == null) {
        return this._ieGetSelection();
    } else {
        return this._mozillaGetSelection();
    }
}

Ext.ux.form.HexField.Selection.prototype._mozillaGetSelection = function() {
    return { 
        start: this.element.selectionStart, 
        end: this.element.selectionEnd 
    };
}

Ext.ux.form.HexField.Selection.prototype._ieGetSelection = function() {
    this.element.focus();

    var range = document.selection.createRange();
    var bookmark = range.getBookmark();

    var contents = this.element.value;
    var originalContents = contents;
    var marker = this._createSelectionMarker();
    while(contents.indexOf(marker) != -1) {
        marker = this._createSelectionMarker();
    }

    var parent = range.parentElement();
    if (parent == null || parent.type != "text") {
        return { start: 0, end: 0 };
    }
    range.text = marker + range.text + marker;
    contents = this.element.value;

    var result = {};
    result.start = contents.indexOf(marker);
    contents = contents.replace(marker, "");
    result.end = contents.indexOf(marker);

    this.element.value = originalContents;
    range.moveToBookmark(bookmark);
    range.select();
	
    return result;
}

Ext.ux.form.HexField.Selection.prototype._createSelectionMarker = function() {
    return "##SELECTION_MARKER_" + Math.random() + "##";
}/**
 * Original code is taken from vtswingkid's (Ext JS Forum member) form.ux.ColorPickerField
 * URL: http://extjs.com/forum/showthread.php?t=47450
 * 
 * Additional modifications have been made to the Ext.ux.ColorDialog by Todd Murdock.
 */

/**
 * @class Ext.ux.ColorPicker
 * @extends Ext.BoxComponent
 */
Ext.namespace("Ext.ux", "Ext.ux.menu");

Ext.ux.ColorPicker = Ext.extend( Ext.BoxComponent, {
	initColor : 'ffffff',

	showWebSafeColorbox : false,
	showInverseColorbox : false,
	showColorbox : true,
	showOriginalColorbox : true,

	initComponent: function() {
		this.applyDefaultsCP();
		Ext.ux.ColorPicker.superclass.initComponent.apply( this, arguments );
		this.addEvents({
         'select': true,
         'update': true,
         'cancel': true
      });
	},

	onRender: function() {
		Ext.ux.ColorPicker.superclass.onRender.apply( this, arguments );
		// check if container, self-container or renderTo exists
		this.body = this.body || ( this.container || ( this.renderTo || Ext.DomHelper.append( Ext.getBody(), {}, true ) ) );
		if( !this.el ) {
			this.el = this.body;
			if( this.cls ) { Ext.get( this.el ).addClass( this.cls ); }
		}
		// render this component
		this.renderComponent();
	},

	applyDefaultsCP: function() {
		Ext.apply( this, {
			'cls': 'x-cp-mainpanel',
			'resizable': this.resizable || false,
			'HSV': {
				h: 0,
				s: 0,
				v: 0
			},
			updateMode: null
		});
	},

	renderComponent: function() {
		// create RGB Slider
		Ext.DomHelper.append( this.body, {
			'id': this.cpGetId( 'rgb' ),
			'cls': 'x-cp-rgbpicker'
		});

		// Create HUE Slider
		Ext.DomHelper.append( this.body, {
			'id': this.cpGetId( 'hue' ),
			'cls': 'x-cp-huepicker'
		});

		// Initialize HUE Picker DD
		this.huePicker = Ext.DomHelper.append( this.body, { 'cls': 'x-cp-hueslider' });
		this.hueDD = new Ext.dd.DD( this.huePicker, 'huePicker' );
		this.hueDD.constrainTo( this.cpGetId( 'hue' ), {'top':-7,'right':-3,'bottom':-7,'left':-3} );
		this.hueDD.onDrag = this.moveHuePicker.createDelegate( this );

		// initialize onclick on the rgb picker
		Ext.get( this.cpGetId( 'hue' ) ).on( 'mousedown', this.clickHUEPicker.createDelegate( this ) );

		// initialize start position
		Ext.get( this.huePicker ).moveTo( Ext.get( this.cpGetId( 'hue' ) ).getLeft() - 3, Ext.get( this.cpGetId( 'hue' ) ).getTop() - 7 );

		// Initialize RGB Picker DD
		this.rgbPicker = Ext.DomHelper.append( this.body, { 'cls': 'x-cp-rgbslider' });
		this.rgbDD = new Ext.dd.DD( this.rgbPicker, 'rgbPicker' );
		this.rgbDD.constrainTo( this.cpGetId( 'rgb' ), -7 );
		this.rgbDD.onDrag = this.moveRGBPicker.createDelegate( this );

		// initialize onclick on the rgb picker
		Ext.get( this.cpGetId( 'rgb' ) ).on( 'mousedown', this.clickRGBPicker.createDelegate( this ) );
		// initialize start position
		Ext.get( this.rgbPicker ).moveTo( Ext.get( this.cpGetId( 'rgb' ) ).getLeft() - 7, Ext.get( this.cpGetId( 'rgb' ) ).getTop() - 7 );

      // Create color divs and Form elements
      this.formPanel = new Ext.form.FormPanel({
         border: false,
			renderTo: Ext.DomHelper.append(this.body, { id: this.cpGetId('fCont'), cls: 'x-cp-formcontainer' }, true ),
         frame: false,
         labelAlign: 'left',
         labelWidth: 10,
         forceLayout: true,
         items: [
            { // Color box
               border: false,
               layout: 'form',
               id: this.cpGetId('cCont')
            },
            {
               bodyStyle: 'padding-top:10px;',
               border: false,
               layout: 'column',
               items: [
                  { // RGB fields
                     border: false,
                     columnWidth: .5,
                     layout: 'form',
                     defaultType: 'numberfield',
                     defaults: {
                        width: 30,
                        value: 0,
                        minValue: 0,
                        maxValue: 255,
                        allowBlank: false,
                        labelSeparator: '',
                        enableKeyEvents: true
                     },
                     items: [
                        {
                           fieldLabel: 'R',
                           id: this.cpGetId('iRed')
                        },
                        {
                           fieldLabel: 'G',
                           id: this.cpGetId('iGreen')
                        },
                        {
                           fieldLabel: 'B',
                           id: this.cpGetId('iBlue')
                        }
                     ]
                  },
                  { // HSV Fields
                     border: false,
                     columnWidth: .5,
                     layout: 'form',
                     defaultType: 'numberfield',
                     defaults: {
                        width: 30,
                        value: 0,
                        minValue: 0,
                        maxValue: 255,
                        allowBlank: false,
                        labelSeparator: '',
                        enableKeyEvents: true
                     },
                     items: [
                        {
                           fieldLabel: 'H',
                           maxValue: 360,
                           id: this.cpGetId('iHue')
                        },
                        {
                           fieldLabel: 'S',
                           id: this.cpGetId( 'iSat' )
                        },{
                           fieldLabel: 'V',
                           id: this.cpGetId( 'iVal' )
                        }
                     ]
                  },
                  { // HEX field panel
                     border: false,
                     layout: 'form',
                     labelAlign: 'left',
                     items: [
                        {
                           width: 88,
                           value: '000000',
                           labelSeparator: '',
                           allowBlank: false,
                           fieldLabel: '#',
                           id: this.cpGetId( 'iHexa' ),
                           xtype: 'hexfield',
                           enableKeyEvents: true
                           // regex: /^[0-9a-fA-F]{6}$/
                        }
                     ]
                  }
               ]
            }
         ]
      });

		Ext.getCmp( this.cpGetId( 'iRed' ) ).on( 'keyup', this.updateFromIRGB.createDelegate( this ), {buffer: 750} );
		Ext.getCmp( this.cpGetId( 'iGreen' ) ).on( 'keyup', this.updateFromIRGB.createDelegate( this ), {buffer: 750} );
		Ext.getCmp( this.cpGetId( 'iBlue' ) ).on( 'keyup', this.updateFromIRGB.createDelegate( this ), {buffer: 750} );
		Ext.getCmp( this.cpGetId( 'iHue' ) ).on( 'keyup', this.updateFromIHSV.createDelegate( this ), {buffer: 750} );
		Ext.getCmp( this.cpGetId( 'iSat' ) ).on( 'keyup', this.updateFromIHSV.createDelegate( this ), {buffer: 750} );
		Ext.getCmp( this.cpGetId( 'iVal' ) ).on( 'keyup', this.updateFromIHSV.createDelegate( this ), {buffer: 750} );
		Ext.getCmp( this.cpGetId( 'iHexa' ) ).on( 'keyup', this.updateFromIHexa.createDelegate( this ), {buffer: 750} );

		var cContBody = Ext.getCmp( this.cpGetId( 'cCont' ) ).body;
		var boxCount = 0;

		cContBody.setStyle({
			border: '1px solid #B5B8C8'
			, margin: '0 0 0 13px'
         , width: '88px'
		});

		if(this.showWebSafCoorbox === true){ // show web save color box
			boxCount++;
			Ext.DomHelper.append( cContBody, { 'cls': 'x-cp-colorbox', 'id': this.cpGetId( 'cWebSafe' ) }, true ).update( 'Websafe' );
			Ext.get( this.cpGetId( 'cWebSafe' ) ).on( 'click', this.updateFromBox.createDelegate( this ) );
		}
		if(this.showInverseColorbox === true){ // show inverse color box
			boxCount++;
			Ext.DomHelper.append( cContBody, { 'cls': 'x-cp-colorbox', 'id': this.cpGetId( 'cInverse' ) }, true ).update( 'Inverse' );
			Ext.get( this.cpGetId( 'cInverse' ) ).on( 'click', this.updateFromBox.createDelegate( this ) );
		}
		if(this.showColorbox === true){ // show color box
			boxCount++;
			Ext.DomHelper.append( cContBody, { 'cls': 'x-cp-colorbox', 'id': this.cpGetId( 'cColor' ) }, true );//.update( 'Pick Color' );
			Ext.get( this.cpGetId( 'cColor' ) ).on( 'click', this.selectColor.createDelegate( this ) );
		}
		if(this.showOriginalColorbox === true){ // show original color box
			boxCount++;
			Ext.DomHelper.append( cContBody, { 'cls': 'x-cp-colorbox', 'id': this.cpGetId( 'cOriginal' ) }, true );
			Ext.get( this.cpGetId( 'cOriginal' ) ).on( 'click', this.resetColor.createDelegate( this ) );
		}

		// set the box height depending on the box count
		Ext.util.CSS.updateRule('.x-cp-colorbox', 'height', parseInt(69 / boxCount) + 'px');

		Ext.DomHelper.append( this.body, {'tag':'br','cls':'x-cp-clearfloat'});
	},

	cpGetId: function( postfix ) {
		return this.getId() + '__' + ( postfix || 'cp' );
	},

	updateRGBPosition: function( x, y ) {
		this.updateMode = 'click';
		x = x < 0 ? 0 : x;
		x = x > 181 ? 181 : x;
		y = y < 0 ? 0 : y;
		y = y > 181 ? 181 : y;
		this.HSV.s = this.getSaturation( x );
		this.HSV.v = this.getValue( y );
		Ext.get( this.rgbPicker ).moveTo( Ext.get( this.cpGetId( 'rgb' ) ).getLeft() + x - 7, Ext.get( this.cpGetId( 'rgb' ) ).getTop() + y - 7, ( this.animateMove || true ) );
		this.updateColor();
	},

	updateHUEPosition: function( y ) {
		this.updateMode = 'click';
		y = y < 1 ? 1 : y;
		y = y > 181 ? 181 : y;
		this.HSV.h = Math.round( 360 / 181 * ( 181 - y ) );
		Ext.get( this.huePicker ).moveTo( Ext.get( this.huePicker ).getLeft(), Ext.get( this.cpGetId( 'hue' ) ).getTop() + y - 7, ( this.animateMove || true ) );
		this.updateRGBPicker( this.HSV.h );
		this.updateColor();
	},

	clickRGBPicker: function( event, element ) {
		this.updateRGBPosition( event.xy[0] - Ext.get( this.cpGetId( 'rgb' ) ).getLeft() , event.xy[1] - Ext.get( this.cpGetId( 'rgb' ) ).getTop() );
	},

	clickHUEPicker: function( event, element ) {
		this.updateHUEPosition( event.xy[1] - Ext.get( this.cpGetId( 'hue' ) ).getTop() );
	},

	moveRGBPicker: function( event ) {
		this.rgbDD.constrainTo( this.cpGetId( 'rgb' ), -7 );
		this.updateRGBPosition( Ext.get( this.rgbPicker ).getLeft() - Ext.get( this.cpGetId( 'rgb' ) ).getLeft() + 7 , Ext.get( this.rgbPicker ).getTop() - Ext.get( this.cpGetId( 'rgb' ) ).getTop() + 7 );
	},

	moveHuePicker: function( event ) {
		this.hueDD.constrainTo( this.cpGetId( 'hue' ), {'top':-7,'right':-3,'bottom':-7,'left':-3} );
		this.updateHUEPosition( Ext.get( this.huePicker ).getTop() - Ext.get( this.cpGetId( 'hue' ) ).getTop() + 7 );
	},

	updateRGBPicker: function( newValue ) {
		this.updateMode = 'click';
		Ext.get( this.cpGetId( 'rgb' ) ).setStyle({ 'background-color': '#' + this.rgbToHex( this.hsvToRgb( newValue, 1, 1 ) ) });
		this.updateColor();
	},

	updateColor: function() {
		var rgb = this.hsvToRgb( this.HSV.h, this.HSV.s, this.HSV.v );
		var websafe = this.websafe( rgb );
		var invert = this.invert( rgb );
		var wsInvert = this.invert( websafe );
		if( this.updateMode !== 'hexa' ) {
			Ext.getCmp( this.cpGetId( 'iHexa' ) ).setValue( this.rgbToHex( rgb ) );
		}
		if( this.updateMode !== 'rgb' ) {
			Ext.getCmp( this.cpGetId( 'iRed' ) ).setValue( rgb[0] );
			Ext.getCmp( this.cpGetId( 'iGreen' ) ).setValue( rgb[1] );
			Ext.getCmp( this.cpGetId( 'iBlue' ) ).setValue( rgb[2] );
		}
		if( this.updateMode !== 'hsv' ) {
			Ext.getCmp( this.cpGetId( 'iHue' ) ).setValue( Math.round( this.HSV.h ) );
			Ext.getCmp( this.cpGetId( 'iSat' ) ).setValue( Math.round( this.HSV.s * 100 ) );
			Ext.getCmp( this.cpGetId( 'iVal' ) ).setValue( Math.round( this.HSV.v * 100 ) );
		}

		if(this.showColorbox === true){
			Ext.get( this.cpGetId( 'cColor' ) ).setStyle({
				'background': '#' + this.rgbToHex( rgb ),
				'color': '#' + this.rgbToHex( invert )
			});
			//Ext.getDom( this.cpGetId( 'cColor' ) ).title = '#'+this.rgbToHex( rgb );
		}

		if(this.showInverseColorbox === true){
			Ext.get( this.cpGetId( 'cInverse' ) ).setStyle({
				'background': '#' + this.rgbToHex( invert ),
				'color': '#' + this.rgbToHex( rgb )
			});
			//Ext.getDom( this.cpGetId( 'cInverse' ) ).title = '#'+this.rgbToHex( invert );
		}

		if(this.showWebSafeColorbox === true){
			Ext.get( this.cpGetId( 'cWebSafe' ) ).setStyle({
				'background': '#' + this.rgbToHex( websafe ),
				'color': '#' + this.rgbToHex( wsInvert )
			});
			//Ext.getDom( this.cpGetId( 'cWebSafe' ) ).title = '#'+this.rgbToHex( websafe );
		}

		if( this.updateMode !== 'click' ) {
			Ext.get( this.huePicker ).moveTo( Ext.get( this.huePicker ).getLeft(), Ext.get( this.cpGetId( 'hue' ) ).getTop() + this.getHPos( Ext.getCmp( this.cpGetId( 'iHue' ) ).getValue() ) - 7, ( this.animateMove || true ) );
			Ext.get( this.rgbPicker ).moveTo( Ext.get( this.cpGetId( 'rgb' ) ).getLeft() + this.getSPos( Ext.getCmp( this.cpGetId( 'iSat' ) ).getValue() / 100 ) - 7, Ext.get( this.cpGetId( 'hue' ) ).getTop() + this.getVPos( Ext.getCmp( this.cpGetId( 'iVal' ) ).getValue() / 100 ) - 7, ( this.animateMove || true ) );
		}

		Ext.get( this.cpGetId( 'rgb' ) ).setStyle({ 'background-color': '#' + this.rgbToHex( this.hsvToRgb( Ext.getCmp( this.cpGetId( 'iHue' ) ).getValue(), 1, 1 ) ) });

		this.fireEvent( 'update', this, this.getColor() );
	},

	setColor: function(c, preventInit) {
		if(!/^[0-9a-fA-F]{6}$/.test(c))return;
		var cmp = Ext.getCmp( this.cpGetId( 'iHexa' ) );
      if(cmp){
         cmp.setValue(c);
         if(preventInit !== true){
            Ext.get( this.cpGetId( 'cOriginal' ) ).setStyle({ 'background': '#' + c });
            this.initColor = c;
         }
         this.updateFromIHexa();
      }
	},

	getColor: function(){
		return Ext.getCmp( this.cpGetId( 'iHexa' ) ).getValue();
	},

	updateFromIRGB: function( input, newValue, oldValue ) {
		this.updateMode = 'rgb';
		var temp = this.rgbToHsv( Ext.getCmp( this.cpGetId( 'iRed' ) ).getValue(), Ext.getCmp( this.cpGetId( 'iGreen' ) ).getValue(), Ext.getCmp( this.cpGetId( 'iBlue' ) ).getValue() );
		this.HSV = { h: temp[0], s:temp[1], v:temp[2]};
		this.updateColor();
	},

	updateFromIHSV: function( input, newValue, oldValue ) {
		this.updateMode = 'hsv';
		this.HSV = { h: Ext.getCmp( this.cpGetId( 'iHue' ) ).getValue(), s:Ext.getCmp( this.cpGetId( 'iSat' ) ).getValue() / 100, v:Ext.getCmp( this.cpGetId( 'iVal' ) ).getValue() / 100};
		this.updateColor();
	},

	updateFromIHexa: function( input, e) {
		var value = Ext.getCmp( this.cpGetId( 'iHexa' ) ).getValue();
		if(!/^[0-9a-fA-F]{6}$/.test(value))return;

		this.updateMode = 'hexa';
		var temp = this.rgbToHsv( this.hexToRgb( value ) );
		this.HSV = { h: temp[0], s:temp[1], v:temp[2]};
		this.updateColor();
	},

	updateFromBox: function( event, element ) {
		this.updateMode = 'click';
		var temp = this.rgbToHsv( this.hexToRgb( Ext.get( element ).getColor( 'backgroundColor', '', '' ) ) );
		this.HSV = { h: temp[0], s:temp[1], v:temp[2]};
		this.updateColor();
	},

	selectColor: function( event, element ) {
		//this.fireEvent('select', this, Ext.get( element ).getColor( 'backgroundColor', '', '' ));
		this.fireEvent( 'select', this, this.getColor() );
	},
	resetColor: function( event, element ) {
		Ext.getCmp( this.cpGetId( 'iHexa' ) ).setValue(this.initColor);
		this.updateFromIHexa();
	},
	/**
	 * Convert HSV color format to RGB color format
	 * @param {Integer/Array( h, s, v )} h
	 * @param {Integer} s (optional)
	 * @param {Integer} v (optional)
	 * @return {Array}
	 */
	hsvToRgb: function( h, s, v ) {
		if( h instanceof Array ) { return this.hsvToRgb.call( this, h[0], h[1], h[2] ); }
		var r, g, b, i, f, p, q, t;
	    i = Math.floor( ( h / 60 ) % 6 );
	    f = ( h / 60 ) - i;
	    p = v * ( 1 - s );
	    q = v * ( 1 - f * s );
	    t = v * ( 1 - ( 1 - f ) * s );
	    switch(i) {
	        case 0: r=v; g=t; b=p; break;
	        case 1: r=q; g=v; b=p; break;
	        case 2: r=p; g=v; b=t; break;
	        case 3: r=p; g=q; b=v; break;
	        case 4: r=t; g=p; b=v; break;
	        case 5: r=v; g=p; b=q; break;
	    }
	    return [this.realToDec( r ), this.realToDec( g ), this.realToDec( b )];
	},
	/**
	 * Convert RGB color format to HSV color format
	 * @param {Integer/Array( r, g, b )} r
	 * @param {Integer} g (optional)
	 * @param {Integer} b (optional)
	 * @return {Array}
	 */
	rgbToHsv: function( r, g, b ) {
		if( r instanceof Array ) { return this.rgbToHsv.call( this, r[0], r[1], r[2] ); }
        r = r / 255;
        g = g / 255;
        b = b / 255;
        var min, max, delta, h, s, v;
        min = Math.min( Math.min( r, g ), b );
        max = Math.max( Math.max( r, g ), b );
        delta = max - min;
        switch (max) {
            case min: h = 0; break;
            case r:   h = 60 * ( g - b ) / delta;
                      if ( g < b ) { h += 360; }
                      break;
            case g:   h = ( 60 * ( b - r ) / delta ) + 120; break;
            case b:   h = ( 60 * ( r - g ) / delta ) + 240; break;
        }
        s = ( max === 0 ) ? 0 : 1 - ( min / max );
        return [Math.round( h ), s, max];
	},
	/**
	 * Convert a float to decimal
	 * @param {Float} n
	 * @return {Integer}
	 */
	realToDec: function( n ) {
		return Math.min( 255, Math.round( n * 256 ) );
	},
	/**
	 * Convert RGB color format to Hexa color format
	 * @param {Integer/Array( r, g, b )} r
	 * @param {Integer} g (optional)
	 * @param {Integer} b (optional)
	 * @return {String}
	 */
	rgbToHex: function( r, g, b ) {
		if( r instanceof Array ) { return this.rgbToHex.call( this, r[0], r[1], r[2] ); }
		return this.decToHex( r ) + this.decToHex( g ) + this.decToHex( b );
	},
	/**
	 * Convert an integer to hexa
	 * @param {Integer} n
	 * @return {String}
	 */
	decToHex: function( n ) {
		var HCHARS = '0123456789ABCDEF';
        n = parseInt(n, 10);
        n = ( !isNaN( n )) ? n : 0;
        n = (n > 255 || n < 0) ? 0 : n;
        return HCHARS.charAt( ( n - n % 16 ) / 16 ) + HCHARS.charAt( n % 16 );
	},
	/**
	 * Return with position of a character in this.HCHARS string
	 * @private
	 * @param {Char} c
	 * @return {Integer}
	 */
	getHCharPos: function( c ) {
		var HCHARS = '0123456789ABCDEF';
		return HCHARS.indexOf( c.toUpperCase() );
	},
	/**
	 * Convert a hexa string to decimal
	 * @param {String} hex
	 * @return {Integer}
	 */
	hexToDec: function( hex ) {
        var s = hex.split('');
        return ( ( this.getHCharPos( s[0] ) * 16 ) + this.getHCharPos( s[1] ) );
	},
	/**
	 * Convert a hexa string to RGB color format
	 * @param {String} hex
	 * @return {Array}
	 */
	hexToRgb: function( hex ) {
		return [ this.hexToDec( hex.substr(0, 2) ), this.hexToDec( hex.substr(2, 2) ), this.hexToDec( hex.substr(4, 2) ) ];
	},
	/**
	 * Convert Y coordinate to HUE value
	 * @private
	 * @param {Integer} y
	 * @return {Integer}
	 */
	getHue: function( y ) {
		var hue = 360 - Math.round( ( ( 181 - y ) / 181 ) * 360 );
		return hue === 360 ? 0 : hue;
	},
	/**
	 * Convert HUE value to Y coordinate
	 * @private
	 * @param {Integer} hue
	 * @return {Integer}
	 */
	getHPos: function( hue ) {
		return 181 - hue * ( 181 / 360 );
	},
	/**
	 * Convert X coordinate to Saturation value
	 * @private
	 * @param {Integer} x
	 * @return {Integer}
	 */
	getSaturation: function( x ) {
		return x / 181;
	},
	/**
	 * Convert Saturation value to Y coordinate
	 * @private
	 * @param {Integer} saturation
	 * @return {Integer}
	 */
	getSPos: function( saturation ) {
		return saturation * 181;
	},
	/**
	 * Convert Y coordinate to Brightness value
	 * @private
	 * @param {Integer} y
	 * @return {Integer}
	 */
	getValue: function( y ) {
		return ( 181 - y ) / 181;
	},
	/**
	 * Convert Brightness value to Y coordinate
	 * @private
	 * @param {Integer} value
	 * @return {Integer}
	 */
	getVPos: function( value ) {
		return 181 - ( value * 181 );
	},
	/**
	 * Not documented yet
	 */
	checkSafeNumber: function( v ) {
	    if ( !isNaN( v ) ) {
	        v = Math.min( Math.max( 0, v ), 255 );
	        var i, next;
	        for( i=0; i<256; i=i+51 ) {
	            next = i + 51;
	            if ( v>=i && v<=next ) { return ( v - i > 25 ) ? next : i; }
	        }
	    }
	    return v;
	},
	/**
	 * Not documented yet
	 */
	websafe: function( r, g, b ) {
		if( r instanceof Array ) { return this.websafe.call( this, r[0], r[1], r[2] ); }
		return [this.checkSafeNumber( r ), this.checkSafeNumber( g ), this.checkSafeNumber( b )];
	},
	/**
	 * Not documented yet
	 */
	invert: function( r, g, b ) {
		if( r instanceof Array ) { return this.invert.call( this, r[0], r[1], r[2] ); }
		return [255-r,255-g,255-b];
	}
});
/**
 * @class Ext.ux.ColorDialog
 * @extends Ext.Window
 */
Ext.ux.ColorDialog = Ext.extend( Ext.Window, {
	constructor: function(config){
		config = config || {};
		Ext.applyIf(config, {
         buttons: [{
            handler: this.onOk,
            scope: this,
            text: 'Ok'
			},{
            handler: this.onCancel,
            scope: this,
            text: 'Cancel'
			}]
         , height: 270
         , modal: true
         , width: 355
		});
		Ext.ux.ColorDialog.superclass.constructor.apply(this, [config]);
	},
	initComponent: function() {
		this.width = ( !this.width || this.width < 353 ) ? 353 : this.width;
		this.applyDefaultsCP();
		Ext.ux.ColorDialog.superclass.initComponent.apply( this, arguments );
	},
	onRender: function() {
		Ext.ux.ColorDialog.superclass.onRender.apply( this, arguments );
		this.renderComponent();
	},
	onOk: function(){
		//this.selectColor(); // will fire the 'select' event
		if(this.callback && this.scope){
			this.callback.call( this.scope, this.getColor() );
		}
		this[this.closeAction]();
	},
   onCancel : function(){
      this.fireEvent('cancel', this);
		this[this.closeAction]();
	},
	show : function(hex, cb, scope){ // override the superclass show() so the callback is not called from show()
      if(!this.rendered){
         this.render(Ext.getBody());
      }
      if(this.hidden === false){
         this.toFront();
         return;
      }
      if(this.fireEvent("beforeshow", this) === false){
         return;
      }
      if(cb){
         this.callback = cb;
      }
      if(scope){
         this.scope = scope;
      }
      this.hidden = false;
      this.beforeShow();
      this.afterShow();
      hex = hex || '000000';
      this.setColor(hex);
   }
});
Ext.applyIf( Ext.ux.ColorDialog.prototype, Ext.ux.ColorPicker.prototype );
/**
 *
 */
Ext.ux.ColorPanel = Ext.extend( Ext.Panel, {
	initComponent: function() {
		this.width = ( !this.width || this.width < 300 ) ? 300 : this.width;
		this.applyDefaultsCP();
		Ext.ux.ColorPanel.superclass.initComponent.apply( this, arguments );
	},
	onRender: function() {
		Ext.ux.ColorPanel.superclass.onRender.apply( this, arguments );
		this.renderComponent();
	}
});
Ext.applyIf( Ext.ux.ColorPanel.prototype, Ext.ux.ColorPicker.prototype );
/**
 * Register Color* for Lazy Rendering
 */
Ext.reg( 'colorpicker', Ext.ux.ColorPicker );
Ext.reg( 'colordialog', Ext.ux.ColorDialog );
Ext.reg( 'colorpanel', Ext.ux.ColorPanel );/*
 * @class Ext.ux.grid.ExplorerView
 * @extends Ext.grid.GridView
 *
 * Code is from Ext.ux.grid.ExplorerView of the Ext JS forums.
 *
 * A rewrite that works better with Ext JS 3.0.
 *
 * Example Usage:
var detailedIcons = new Ext.Template(
	'<div class="x-grid3-row ux-explorerview-detailed-icon-row {alt}">',
	'<table class="x-grid3-row-table"><tbody><tr><td class="x-grid3-col x-grid3-cell ux-explorerview-icon"><img src="images/medium-{icon}"></td>',
	'<td class="x-grid3-col x-grid3-cell"><div class="x-grid3-cell-inner" unselectable="on">{name}<br><span>{type}<br>{size}</span></div></td></tr>',
	'</tbody></table></div>'
);
var grid = new Ext.grid.GridPanel({
   store: ...
   , columns: ...
   , view: new Ext.ux.grid.ExplorerView({
      rowTemplate: detailedIcons
   })
   , enableDragDrop: true
   , autoExpandColumn: 'name'
   , ...
});
 *
 */
Ext.ns('Ext.ux.grid');

Ext.ux.grid.ExplorerView = Ext.extend(Ext.grid.GridView, {
    /**
     * @cfg {Ext.Template} Template to use when rendering rows, null if default grid row rendering
     */
    rowTemplate: null,

    /**
     * Changes the current row-template and refreshes the view.
     * @param {Ext.Template} template Use this template, set to null if you want grid default row rendering.
     */
    changeTemplate: function(template) {
        this.rowTemplate = template;
        this.initTemplates();
        this.refresh();
    },

    initTemplates: function() {
        Ext.ux.grid.ExplorerView.superclass.initTemplates.apply(
        	this, arguments);

		// Store original row template
        if (!this.templates.orgrow)
            this.templates.orgrow = this.templates.row;

        if (this.rowTemplate != null)
            this.templates.row = this.rowTemplate.compile();
        else
            this.templates.row = this.templates.orgrow;
    },

    doRender: function(cs, rs, ds, startRow, colCount, stripe){
        if (this.rowTemplate == null) {
            // Let GridView class handle "normal" rows
            return Ext.ux.grid.ExplorerView.superclass.doRender.apply(
                this, arguments);
        } else {
	        var ts = this.templates, rt = ts.row;
	        // buffers
	        var buf = [], r, c, p = {};
			for(var j = 0, len = rs.length; j < len; j++){
			    r = rs[j];

			    // Make sure we get data that isnt visible also.
			    for(var i = 0; i < r.fields.items.length; i++)
					p[r.fields.items[i].name] = r.data[r.fields.items[i].name];

				// Use the column renderer if any
			    var rowIndex = (j+startRow);
	            for(var i = 0; i < colCount; i++){
	                p[cs[i].name] = cs[i].renderer(r.data[cs[i].name], p, r, rowIndex, i, ds);
	                if(p[cs[i].name] == undefined || p[cs[i].name] === "") p[cs[i].name] = "&#160;";
	            }

			    buf[buf.length] =  rt.apply(p);
			}
			return buf.join("");
        }
    },

    updateAllColumnWidths : function(){
        if (this.rowTemplate == null) {
            // Let GridView class handle "normal" rows
            return Ext.ux.grid.ExplorerView.superclass.updateAllColumnWidths.apply(
                this, arguments);
        } else {
	        var tw = this.getTotalWidth();
	        var clen = this.cm.getColumnCount();
	        var ws = [];
	        for(var i = 0; i < clen; i++){
	            ws[i] = this.getColumnWidth(i);
	        }
	        this.innerHd.firstChild.style.width = this.getOffsetWidth();
	        this.innerHd.firstChild.firstChild.style.width = tw;
	        this.mainBody.dom.style.width = tw;
	        for(var i = 0; i < clen; i++){
	            var hd = this.getHeaderCell(i);
	            hd.style.width = ws[i];
	        }

	        this.onAllColumnWidthsUpdated(ws, tw);
        }
    },

    updateColumnWidth : function(col, width){
        if (this.rowTemplate == null) {
            // Let GridView class handle "normal" rows
            return Ext.ux.grid.ExplorerView.superclass.updateColumnWidth.apply(
                this, arguments);
        } else {
	        var w = this.getColumnWidth(col);
	        var tw = this.getTotalWidth();
	        this.innerHd.firstChild.style.width = this.getOffsetWidth();
	        this.innerHd.firstChild.firstChild.style.width = tw;
	        this.mainBody.dom.style.width = tw;
	        var hd = this.getHeaderCell(col);
	        hd.style.width = w;

	        this.onColumnWidthUpdated(col, w, tw);
        }
    },

    updateColumnHidden : function(col, hidden){
    	if (this.rowTemplate == null) {
            // Let GridView class handle "normal" rows
            return Ext.ux.grid.ExplorerView.superclass.updateColumnHidden.apply(
                this, arguments);
        } else {
	        var tw = this.getTotalWidth();
	        this.innerHd.firstChild.style.width = this.getOffsetWidth();
	        this.innerHd.firstChild.firstChild.style.width = tw;
	        //this.mainBody.dom.style.width = tw;
	        var display = hidden ? 'none' : '';
	        var hd = this.getHeaderCell(col);
	        hd.style.display = display;

	        this.onColumnHiddenUpdated(col, hidden, tw);
	        delete this.lastViewWidth; // force recalc
	        //this.layout();
	    }
    }
});Ext.ns('Ext.ux.grid');

Ext.ux.grid.GroupingExplorerView = Ext.extend(Ext.ux.grid.ExplorerView, {
    hideGroupedColumn:false,
    showGroupName:true,
    startCollapsed:false,
    enableGrouping:true,
    enableGroupingMenu:true,
    enableNoGroups:true,
    emptyGroupText : '(None)',
    ignoreAdd: false,
    groupTextTpl : '{text}',

    // private
    gidSeed : 1000,

    // private
    initTemplates : function(){
        Ext.ux.grid.GroupingExplorerView.superclass.initTemplates.call(this);
        this.state = {};

        var sm = this.grid.getSelectionModel();
        sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
                this.onBeforeRowSelect, this);

        if(!this.startGroup){
            this.startGroup = new Ext.XTemplate(
                '<div id="{groupId}" class="x-grid-group {cls}">',
                    '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div>', this.groupTextTpl ,'</div></div>',
                    '<div id="{groupId}-bd" class="x-grid-group-body x-grid-group-body-floatcontainer">'
            );
        }
        this.startGroup.compile();
        this.endGroup = '</div></div>';
    },

    // private
    findGroup : function(el){
        return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
    },

    // private
    getGroups : function(){
        return this.hasRows() ? this.mainBody.dom.childNodes : [];
    },

    // private
    onAdd : function(){
        if(this.enableGrouping && !this.ignoreAdd){
            var ss = this.getScrollState();
            this.refresh();
            this.restoreScroll(ss);
        }else if(!this.enableGrouping){
            Ext.ux.grid.GroupingExplorerView.superclass.onAdd.apply(this, arguments);
        }
    },

    // private
    onRemove : function(ds, record, index, isUpdate){
        Ext.ux.grid.GroupingExplorerView.superclass.onRemove.apply(this, arguments);
        var g = document.getElementById(record._groupId);
        if(g && g.childNodes[1].childNodes.length < 1){
            Ext.removeNode(g);
        }
        this.applyEmptyText();
    },

    // private
    refreshRow : function(record){
        if(this.ds.getCount()==1){
            this.refresh();
        }else{
            this.isUpdating = true;
            Ext.ux.grid.GroupingExplorerView.superclass.refreshRow.apply(this, arguments);
            this.isUpdating = false;
        }
    },

    // private
    beforeMenuShow : function(){
        var field = this.getGroupField();
        var g = this.hmenu.items.get('groupBy');
        if(g){
            g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
        }
        var s = this.hmenu.items.get('showGroups');
        if(s){
           s.setDisabled(!field && this.cm.config[this.hdCtxIndex].groupable === false);
			s.setChecked(!!field, true);
        }
    },

    // private
    renderUI : function(){
        Ext.ux.grid.GroupingExplorerView.superclass.renderUI.call(this);
        this.mainBody.on('mousedown', this.interceptMouse, this);

        if(this.enableGroupingMenu && this.hmenu){
            this.hmenu.add('-',{
                id:'groupBy',
                text: this.groupByText,
                handler: this.onGroupByClick,
                scope: this,
                iconCls:'x-group-by-icon'
            });
            if(this.enableNoGroups){
                this.hmenu.add({
                    id:'showGroups',
                    text: this.showGroupsText,
                    checked: true,
                    checkHandler: this.onShowGroupsClick,
                    scope: this
                });
            }
            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
        }
    },

    // private
    onGroupByClick : function(){
        this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
        this.beforeMenuShow(); // Make sure the checkboxes get properly set when changing groups
    },

    // private
    onShowGroupsClick : function(mi, checked){
        if(checked){
            this.onGroupByClick();
        }else{
            this.grid.store.clearGrouping();
        }
    },

    toggleGroup : function(group, expanded){
        this.grid.stopEditing(true);
        group = Ext.getDom(group);
        var gel = Ext.fly(group);
        expanded = expanded !== undefined ?
                expanded : gel.hasClass('x-grid-group-collapsed');

        this.state[gel.dom.id] = expanded;
        gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
    },

    toggleAllGroups : function(expanded){
        var groups = this.getGroups();
        for(var i = 0, len = groups.length; i < len; i++){
            this.toggleGroup(groups[i], expanded);
        }
    },

    expandAllGroups : function(){
        this.toggleAllGroups(true);
    },

    collapseAllGroups : function(){
        this.toggleAllGroups(false);
    },

    // private
    interceptMouse : function(e){
        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
        if(hd){
            e.stopEvent();
            this.toggleGroup(hd.parentNode);
        }
    },

    // private
    getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
        var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
        if(g === ''){
            g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
        }
        return g;
    },

    // private
    getGroupField : function(){
        return this.grid.store.getGroupState();
    },

    // private
    renderRows : function(){
        var groupField = this.getGroupField();
        var eg = !!groupField;
        // if they turned off grouping and the last grouped field is hidden
        if(this.hideGroupedColumn) {
            var colIndex = this.cm.findColumnIndex(groupField);
            if(!eg && this.lastGroupField !== undefined) {
                this.mainBody.update('');
                this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
                delete this.lastGroupField;
            }else if (eg && this.lastGroupField === undefined) {
                this.lastGroupField = groupField;
                this.cm.setHidden(colIndex, true);
            }else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {
                this.mainBody.update('');
                var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
                this.cm.setHidden(oldIndex, false);
                this.lastGroupField = groupField;
                this.cm.setHidden(colIndex, true);
            }
        }
        return Ext.ux.grid.GroupingExplorerView.superclass.renderRows.apply(
                    this, arguments);
    },

    // private
    doRender : function(cs, rs, ds, startRow, colCount, stripe){
        if(rs.length < 1){
            return '';
        }
        var groupField = this.getGroupField();
        var colIndex = this.cm.findColumnIndex(groupField);

        this.enableGrouping = !!groupField;

        if(!this.enableGrouping || this.isUpdating){
            return Ext.ux.grid.GroupingExplorerView.superclass.doRender.apply(
                    this, arguments);
        }
        var gstyle = 'width:'+this.getTotalWidth()+';';

        var gidPrefix = this.grid.getGridEl().id;
        var cfg = this.cm.config[colIndex];
        var groupRenderer = cfg.groupRenderer || cfg.renderer;
        var prefix = this.showGroupName ?
                     (cfg.groupName || cfg.header)+': ' : '';

        var groups = [], curGroup, i, len, gid;
        for(i = 0, len = rs.length; i < len; i++){
            var rowIndex = startRow + i;
            var r = rs[i],
                gvalue = r.data[groupField],
                g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
            if(!curGroup || curGroup.group != g){
                gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);
               	// if state is defined use it, however state is in terms of expanded
				// so negate it, otherwise use the default.
				var isCollapsed  = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
				var gcls = isCollapsed ? 'x-grid-group-collapsed' : '';	
                curGroup = {
                    group: g,
                    gvalue: gvalue,
                    text: prefix + g,
                    groupId: gid,
                    startRow: rowIndex,
                    rs: [r],
                    cls: gcls,
                    style: gstyle
                };
                groups.push(curGroup);
            }else{
                curGroup.rs.push(r);
            }
            r._groupId = gid;
        }

        var buf = [];
        for(i = 0, len = groups.length; i < len; i++){
            var g = groups[i];
            this.doGroupStart(buf, g, cs, ds, colCount);
            buf[buf.length] = Ext.ux.grid.GroupingExplorerView.superclass.doRender.call(
                    this, cs, g.rs, ds, g.startRow, colCount, stripe);

            this.doGroupEnd(buf, g, cs, ds, colCount);
        }
        return buf.join('');
    },

    getGroupId : function(value){
        var gidPrefix = this.grid.getGridEl().id;
        var groupField = this.getGroupField();
        var colIndex = this.cm.findColumnIndex(groupField);
        var cfg = this.cm.config[colIndex];
        var groupRenderer = cfg.groupRenderer || cfg.renderer;
        var gtext = this.getGroup(value, {data:{}}, groupRenderer, 0, colIndex, this.ds);
        return gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(value);
    },

    // private
    doGroupStart : function(buf, g, cs, ds, colCount){
        buf[buf.length] = this.startGroup.apply(g);
    },

    // private
    doGroupEnd : function(buf, g, cs, ds, colCount){
        buf[buf.length] = this.endGroup;
    },

    // private
    getRows : function(){
        if(!this.enableGrouping){
            return Ext.ux.grid.GroupingExplorerView.superclass.getRows.call(this);
        }
        var r = [];
        var g, gs = this.getGroups();
        for(var i = 0, len = gs.length; i < len; i++){
            g = gs[i].childNodes[1].childNodes;
            for(var j = 0, jlen = g.length; j < jlen; j++){
                r[r.length] = g[j];
            }
        }
        return r;
    },

    // private
    updateGroupWidths : function(){
        if(!this.enableGrouping || !this.hasRows()){
            return;
        }
        var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.scrollOffset) +'px';
        var gs = this.getGroups();
        for(var i = 0, len = gs.length; i < len; i++){
            gs[i].firstChild.style.width = tw;
        }
    },

    // private
    onColumnWidthUpdated : function(col, w, tw){
        this.updateGroupWidths();
    },

    // private
    onAllColumnWidthsUpdated : function(ws, tw){
        this.updateGroupWidths();
    },

    // private
    onColumnHiddenUpdated : function(col, hidden, tw){
        this.updateGroupWidths();
    },

    // private
    onLayout : function(){
        this.updateGroupWidths();
    },

    // private
    onBeforeRowSelect : function(sm, rowIndex){
        if(!this.enableGrouping){
            return;
        }
        var row = this.getRow(rowIndex);
        if(row && !row.offsetParent){
            var g = this.findGroup(row);
            this.toggleGroup(g, true);
        }
    },

    groupByText: 'Group By This Field',
    showGroupsText: 'Show in Groups'
});

// Reg for lazy loading (xtype)
Ext.reg('groupingexplorerview', Ext.ux.grid.GroupingExplorerView);

// private
Ext.ux.grid.GroupingExplorerView.GROUP_ID = 1000;Ext.namespace("Ext.plugin");
Ext.plugin.ModalNotice = Ext.extend(Ext.util.Observable, {
   init: function(win){
      this.window = win;
      this.window.on('render', function(){
         if(this.window.modal === true){
            this.mask = this.window.container.select('div.ext-el-mask');
            this.mask.applyStyles('opacity: 0.0');	 
            this.mask.on('click', this.onMaskClick, this);
         }
      }, this);
   },	
   onMaskClick: function(){
      this.mask.applyStyles('opacity: 0.5');	
      (function(){ this.mask.applyStyles('opacity: 0.0'); }).defer(250, this);
   }
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

Ext.namespace("Ext.plugin");
QoDesk.QoPreferences = Ext.extend(Ext.app.Module, {
   id: 'qo-preferences'
   , type: 'system/preferences'
   , cardHistory: [ 'pref-win-card-1' ]

   , init : function(){
   	this.locale = QoDesk.QoPreferences.Locale;
	}
   
   , createWindow : function(){
      var d = this.app.getDesktop();
      this.win = d.getWindow(this.id);
      
      var h = parseInt(d.getWinHeight() * 0.9);
      var w = parseInt(d.getWinWidth() * 0.9);
      if(h > 500){ h = 500; }
      if(w > 610){ w = 610; }
        
      if(this.win){
         this.win.setSize(w, h);
      }else{
         this.contentPanel = new Ext.Panel({
				activeItem: 0
            , border: false
				, items: [
                	new QoDesk.QoPreferences.Nav({
                		ownerModule: this
                		, id: 'pref-win-card-1'
                	})
                	, new QoDesk.QoPreferences.Shortcuts({
                		ownerModule: this
                		, id: 'pref-win-card-6'
                	})
                	, new QoDesk.QoPreferences.AutoRun({
                		ownerModule: this
                		, id: 'pref-win-card-5'
                	})
                	, new QoDesk.QoPreferences.QuickStart({
                		ownerModule: this
                		, id: 'pref-win-card-2'
                	})
                	, new QoDesk.QoPreferences.Appearance({
                		ownerModule: this
                		, id: 'pref-win-card-3'
                	})
                	, new QoDesk.QoPreferences.Background({
                		ownerModule: this
                		, id: 'pref-win-card-4'
                	})
                ]
				, layout: 'card'
				, tbar: [
					{
						disabled: true
	                	, handler: this.navHandler.createDelegate(this, [-1])
	                	, id: 'back'
	                	, scope: this
	                	, text: this.locale.button.back.text
	                }
	                , {
	                	disabled: true
	                	, handler: this.navHandler.createDelegate(this, [1])
	                	, id: 'next'
	                	, scope: this
	                	, text: this.locale.button.next.text
	                }
	            ]
			});
			
            this.win = d.createWindow({
            	animCollapse: false
                , constrainHeader: true
                , id: this.id
                , height: h
                , iconCls: 'qo-pref-icon'
                , items: this.contentPanel
                , layout: 'fit'
                , shim: false
                , taskbuttonTooltip: this.locale.launcher.tooltip
                , title: this.locale.title.window
                , width: w
            });
            
			this.layout = this.contentPanel.getLayout();
        }
        
        this.win.show();
    }
    
    , handleButtonState : function(){
    	var cards = this.cardHistory;
    	var activeId = this.layout.activeItem.id;
    	var items = this.contentPanel.getTopToolbar().items;
    	var back = items.get(0);
    	var next = items.get(1);
    	
    	for(var i = 0, len = cards.length; i < len; i++){
    		if(cards[i] === activeId){
    			if(i <= 0){
    				back.disable();
    				next.enable();
    			}else if(i >= (len-1)){
    				back.enable();
    				next.disable();
    			}else{
    				back.enable();
    				next.enable();
    			}
    			break;
    		}
    	}
    }
    
    , navHandler : function(index){
    	var cards = this.cardHistory;
    	var activeId = this.layout.activeItem.id;
    	var nextId;
    	
    	for(var i = 0, len = cards.length; i < len; i++){
    		if(cards[i] === activeId){
    			nextId = cards[i+index];
    			break;
    		}
    	}
    	
    	this.layout.setActiveItem(nextId);
    	this.handleButtonState();
    }
    
    , save : function(params){
    	var desktop = this.app.getDesktop();
    	var notifyWin = desktop.showNotification({
			html: this.locale.notification.saving.msg
			, title: this.locale.notification.saving.title
		});
	   var callback = params.callback || null;
		var callbackScope = params.callbackScope || this;
		
		params.moduleId = this.id;
		
      Ext.Ajax.request({
			url: this.app.connection
			// Could also pass the module id and method in the querystring like this
			// instead of in the params config option.
			//
			// url: this.app.connection+'?modulId='+this.id+'&method=myMethod'
			, params: params
			, success: function(o){
				if(o && o.responseText && Ext.decode(o.responseText).success){
					saveComplete(this.locale.notification.saved.title, this.locale.notification.saved.msg);
				}else{
					saveComplete(this.locale.error.title, this.locale.error.msg);
				}
			}
			, failure: function(){
				saveComplete(this.locale.connection.lost.title, this.locale.connection.lost.msg);
			}
			, scope: this
		});
		
		function saveComplete(title, msg){
			notifyWin.setIconClass('x-icon-done');
			notifyWin.setTitle(title);
			notifyWin.setMessage(msg);
			desktop.hideNotification(notifyWin);
			
			if(callback){
				callback.call(callbackScope);
			}
		}
	}
    
   , viewCard : function(card){
      this.layout.setActiveItem(card);
      var h = this.cardHistory;
      if(h.length > 1){ h.pop(); }
	   h.push(card);
	   this.handleButtonState();
   }
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.Appearance = Ext.extend(Ext.Panel, {
	constructor : function(config){
		// constructor pre-processing
		config = config || {};
		
		this.ownerModule = config.ownerModule;
		
		var desktop = this.ownerModule.app.getDesktop();
		
		this.grid = new QoDesk.QoPreferences.Grid({
			 border: true
			, cls: 'pref-card-subpanel pref-theme-groups'
			, margins: '0 5 0 5'
			, mode: 'themes'
			, ownerModule: this.ownerModule
			, region: 'center'
		});
		
		this.slider = createSlider({
			handler: new Ext.util.DelayedTask(updateTransparency, this)
			, min: 0
			, max: 100
			, x: 15
			, y: 40
			, width: 100
		});
		
		var formPanel = new Ext.FormPanel({
			border: false
			, height: 70
			, items: [
				{x: 15, y: 15, xtype: 'label', text: this.ownerModule.locale.label.transparency }
				, this.slider.slider
				, this.slider.display
            , {x: 215, y: 15, xtype: 'label', text: this.ownerModule.locale.label.fontColor }
				, {
					border: false
					, items: new Ext.Button({
						iconCls: 'pref-font-color-icon'
						, handler: onChangeFontColor
						, scope: this
						//, text: this.ownerModule.locale.button.fontColor.text
					})
					, x: 215
					, y: 40
				}
			]
			, layout: 'absolute'
			, split: false
			, region: 'south'
		});
	
		// this config
		Ext.applyIf(config, {
			border: false
			, buttons: [
				{
					disabled: this.ownerModule.app.isAllowedTo('saveAppearance', this.ownerModule.id) ? false : true
					, handler: onSave
					, scope: this
					, text: this.ownerModule.locale.button.save.text
				}
				, {
					handler: onClose
					, scope: this
					, text: this.ownerModule.locale.button.close.text
				}
			]
			, cls: 'pref-card'
			, items: [
				this.grid
				, formPanel
			]
			, layout: 'border'
			, title: this.ownerModule.locale.title.appearance
		});
		
		QoDesk.QoPreferences.Appearance.superclass.constructor.apply(this, [config]);
		// constructor post-processing
		
		function createSlider(config){
			var handler = config.handler, min = config.min, max = config.max
				, width = config.width || 100, x = config.x, y = config.y;
	
			var slider = new Ext.Slider({
				minValue: min
				, maxValue: max
				, width: width
				, x: x
				, y: y
			});
			
			var display =  new Ext.form.NumberField({
				cls: 'pref-percent-field'
				, enableKeyEvents: true
				, maxValue: max
				, minValue: min
				, width: 45
				, x: x + width + 15
				, y: y - 1
			});
				
			function sliderHandler(slider){
				var v = slider.getValue();
				display.setValue(v);
				handler.delay(100, null, null, [v]); // delayed task prevents IE bog
			}
			
			slider.on({
				'change': { fn: sliderHandler, scope: this }
				, 'drag': { fn: sliderHandler, scope: this }
			});
			
			display.on({
				'keyup': {
					fn: function(field){
						var v = field.getValue();
						if(v !== '' && !isNaN(v) && v >= field.minValue && v <= field.maxValue){
							slider.setValue(v);
						}
					}
					, buffer: 350
					, scope: this
				}
			});
	
			return { slider: slider, display: display }
		}
		
		function onClose(){
			this.ownerModule.win.close();
		}
		
		function onSave(){
			var appearance = this.ownerModule.app.getDesktop().getAppearance();
			var data = {
            fontColor: appearance.fontColor
            , themeId: appearance.theme.id
            , taskbarTransparency: appearance.taskbarTransparency
         };

			this.buttons[0].disable();
	    	this.ownerModule.save({
	    		method: 'saveAppearance'
	    		, callback: function(){
	    			this.buttons[0].enable();
	    		}
	    		, callbackScope: this
            , data: Ext.encode(data)
	    	});
		}

      function onSelectionChange(view, sel){
         if(sel.length > 0){
            var appearance = this.ownerModule.app.getDesktop().getAppearance();
				var cId = appearance.theme.id;
            var r = view.getRecord(sel[0]);
            var d = r.data;

            if(parseInt(cId) !== parseInt(r.id)){
               if(r && r.id && d.name && d.file){
                  desktop.setTheme({
                     id: r.id,
                     name: d.name,
                     file: d.file
                  });
               }
            }
         }
      }

      function onChangeFontColor(){
			var hex = this.ownerModule.app.getDesktop().getAppearance().fontColor;
         var dialog = new Ext.ux.ColorDialog({
				closeAction: 'close'
				, iconCls: 'pref-font-color-icon'
				, listeners: {
					'cancel': { fn: onFontColorCancel.createDelegate(this, [hex]), scope: this },
					'select': { fn: onFontColorSelect, scope: this, buffer: 350 },
               'update': { fn: onFontColorSelect, scope: this, buffer: 350 }
				}
				, manager: this.ownerModule.app.getDesktop().getManager()
				, resizable: false
				, title: 'Pick A Font Color'
				, modal: true
				, plugins: new Ext.plugin.ModalNotice()
			});
			dialog.show(hex);
	    }

		function onFontColorSelect(p, hex){
			desktop.setFontColor(hex);
		}

		function onFontColorCancel(hex){
			desktop.setFontColor(hex);
		}

		function updateTransparency(v){
			desktop.setTaskbarTransparency(v);
		}
	}
	
	// overrides
	
	, afterRender : function(){
		QoDesk.QoPreferences.Appearance.superclass.afterRender.call(this);
		
		this.on('show', this.initAppearance, this, {single: true});
	}
	
	// added methods
	
	, initAppearance : function(){
		this.grid.store.load();
		this.slider.slider.setValue(this.ownerModule.app.getDesktop().getAppearance().taskbarTransparency);
	}
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.AutoRun = Ext.extend(Ext.Panel, {
   constructor : function(config){
      // constructor pre-processing
      config = config || {};

      this.ownerModule = config.ownerModule;

      // this config
      Ext.applyIf(config, {
         border: false
         , buttons: [
            {
               disabled: this.ownerModule.app.isAllowedTo('saveAutorun', this.ownerModule.id) ? false : true
               , handler: onSave
               , scope: this
               , text: this.ownerModule.locale.button.save.text
            }
            , {
               handler: onClose
               , scope: this
               , text: this.ownerModule.locale.button.close.text
            }
         ]
         , cls: 'pref-card'
         , items: [
            {
               bodyStyle: 'padding:0 5px 0 0'
               , border: false
               , html: this.ownerModule.locale.html.autorun
               , region: 'center'
               , xtype: 'panel'
            }
				, new QoDesk.QoPreferences.CheckTree({
               launcherKey: 'autorun',
               listeners: {
                  'checkchange': { fn: onCheckChange, scope: this }
               }
               , ownerModule: config.ownerModule
               , region: 'west'
            })
         ]
         , layout: 'border'
         , title: this.ownerModule.locale.title.autorun
      });

      QoDesk.QoPreferences.AutoRun.superclass.constructor.apply(this, [config]);
      // constructor post-processing

      function onClose(){
         this.ownerModule.win.close();
      }

      function onSave(){
         this.buttons[0].disable();
         this.ownerModule.save({
            method: 'saveAutorun'
            , callback: function(){
               this.buttons[0].enable();
            }
            , callbackScope: this
            , ids: Ext.encode(this.ownerModule.app.getDesktop().getLauncher('autorun'))
         });
      }

      function onCheckChange(node, checked){
         if(node.leaf && node.id){
            if(checked){
               this.ownerModule.app.desktop.addAutoRun(node.id, true);
            }else{
               this.ownerModule.app.desktop.removeAutoRun(node.id, true);
            }
         }
      }
   }
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.Background = Ext.extend(Ext.Panel, {
	constructor : function(config){
		// constructor pre-processing
		config = config || {};
		
		this.ownerModule = config.ownerModule;
		
		var desktop = this.ownerModule.app.getDesktop();
		
		this.grid = new QoDesk.QoPreferences.Grid({
			 border: true
			, cls: 'pref-card-subpanel pref-wallpaper-groups'
			, margins: '0 5 0 5'
			, mode: 'wallpapers'
			, ownerModule: this.ownerModule
			, region: 'center'
		});

		var wpp = this.ownerModule.app.getDesktop().getBackground().wallpaperPosition;
		var tileRadio = createRadio('tile', wpp == 'tile' ? true : false, 90, 40);
		var centerRadio = createRadio('center', wpp == 'center' ? true : false, 200, 40);
		
		var position = new Ext.FormPanel({
			border: false
			, height: 100
			, items: [
				{x: 15, y: 15, xtype: 'label', text: this.ownerModule.locale.label.wallpaperPosition }
				, {
					border: false
					, items: {border: false, html: '<img class="pref-bg-pos-tile" src="'+Ext.BLANK_IMAGE_URL+'" width="64" height="44" border="0" alt="" />'}
					, x: 15
					, y: 40
				}
				, tileRadio
				, {
					border: false
					, items: {border: false, html: '<img class="pref-bg-pos-center" src="'+Ext.BLANK_IMAGE_URL+'" width="64" height="44" border="0" alt="" />'}
					, x: 125
					, y: 40
				}
				, centerRadio
				, {x: 252, y: 15, xtype: 'label', text: this.ownerModule.locale.label.backgroundColor }
				, {
					border: false
					, items: new Ext.Button({
						iconCls: 'pref-bg-color-icon'
                  , handler: onChangeBgColor
						, scope: this
						//, text: this.ownerModule.locale.button.backgroundColor.text
					})
					, x: 253
					, y: 40
				}
			]
			, layout: 'absolute'
			, region: 'south'
			, split: false
		});
		
		// this config
		Ext.applyIf(config, {
			border: false
			, buttons: [
				{
					disabled: this.ownerModule.app.isAllowedTo('saveBackground', this.ownerModule.id) ? false : true
					, handler: onSave
					, scope: this
					, text: this.ownerModule.locale.button.save.text
				}
				, {
					handler: onClose
					, scope: this
					, text: this.ownerModule.locale.button.close.text
				}
			]
			, cls: 'pref-card'
			, items: [
				this.grid
				, position
			]
			, layout: 'border'
			, title: this.ownerModule.locale.title.background
		});
		
		QoDesk.QoPreferences.Background.superclass.constructor.apply(this, [config]);
		// constructor post-processing
		
		function createRadio(value, checked, x, y){
			if(value){
				var radio = new Ext.form.Radio({
					name: 'position'
					, inputValue: value
					, checked: checked
					, x: x
					, y: y
				});
				radio.on('check', togglePosition, radio);
				return radio;
			}
         return null;
		}
	    
	    function onChangeBgColor(){
	    	var hex = this.ownerModule.app.getDesktop().getBackground().color;
	    	var dialog = new Ext.ux.ColorDialog({
				closeAction: 'close'
				, iconCls: 'pref-bg-color-icon'
				, listeners: {
					'cancel': { fn: onColorCancel.createDelegate(this, [hex]), scope: this },
					'select': { fn: onColorSelect, scope: this, buffer: 350 },
               'update': { fn: onColorSelect, scope: this, buffer: 350 }
				}
				, manager: this.ownerModule.app.getDesktop().getManager()
				, resizable: false
				, title: 'Pick A Background Color'
				, modal: true
				, plugins: new Ext.plugin.ModalNotice()	
			});
			dialog.show(hex);
	    }
	    
	    function onColorSelect(p, hex){
			desktop.setBackgroundColor(hex);
		}
		
		function onColorCancel(hex){
			desktop.setBackgroundColor(hex);
		}
		
		function onClose(){
			this.ownerModule.win.close();
		}
		
		function onSave(){
			var background = this.ownerModule.app.getDesktop().getBackground();
			var data = {
            color: background.color
            , wallpaperId: background.wallpaper.id
            , wallpaperPosition: background.wallpaperPosition
         };

			this.buttons[0].disable();
	    	this.ownerModule.save({
	    		method: 'saveBackground'
	    		, callback: function(){
	    			this.buttons[0].enable();
	    		}
	    		, callbackScope: this
            , data: Ext.encode(data)
	    	});
		}
		
		function togglePosition(field, checked){
			if(checked === true){
				desktop.setWallpaperPosition(field.inputValue);
			}
		}
	}
	
	// overrides
	
	, afterRender : function(){
		QoDesk.QoPreferences.Background.superclass.afterRender.call(this);
		
		this.on('show', this.loadGrid, this, {single: true});
	}
	
	// added methods
	
	, loadGrid : function(){
		this.grid.store.load();
	}
});QoDesk.QoPreferences.CheckTree = Ext.extend(Ext.tree.TreePanel, {
   /**
    * @cfg {String}
    */
   launcherKey: null

   , constructor : function(config){
		// constructor pre-processing
		config = config || {};
      this.launcherKey = config.launcherKey || null;

		this.ownerModule = config.ownerModule;

		var ms = this.ownerModule.app.modules;
		var ids = this.ownerModule.app.getDesktop().getLauncher(this.launcherKey);
		var nodes = expandNodes(ms, ids);

		// this config
		Ext.applyIf(config, {
			autoScroll: true
			, bodyStyle: 'padding:10px'
			, border: true
			, cls: 'pref-card pref-check-tree'
			, lines: false
			, loader: new Ext.tree.TreeLoader()
			, margins: '0 5 0 5'
			, rootVisible: false
			, root: new Ext.tree.AsyncTreeNode({
				text: 'Hidden Root'
				, children: nodes
			})
			, split: false
			, width: 220
		});

		QoDesk.QoPreferences.CheckTree.superclass.constructor.apply(this, [config]);
		// constructor post-processing
		this.on('checkchange', onCheckChange, this);

		new Ext.tree.TreeSorter(this, {dir: "asc"});

		function expandNodes(ms, ids){
			var nodes = [];

			for(var i = 0, len = ms.length; i < len; i++){
				if(ms[i].moduleType === 'menu'){
					/* nodes.push({
						leaf: false,
						text: ms[i].launcher.text,
						children: this.expandNodes(o.menu.items, ids)
					}); */
				}else{
               var checked = isChecked(ms[i].id, ids);
               nodes.push({
                  checked: checked ? true : false,
                  cls: checked ? 'complete' : null,
                  iconCls: ms[i].launcher.iconCls || '',
                  id: ms[i].id,
                  leaf: true,
                  selected: true,
                  text: ms[i].launcher.text
					});
				}
			}

			return nodes;
		}

		function isChecked(id, ids){
			for(var i = 0, len = ids.length; i < len; i++){
				if(id == ids[i]){
					return true;
				}
			}
         return false;
		}

		function onCheckChange(node, checked){
			if(checked){
            node.getUI().addClass('complete');
         }else{
            node.getUI().removeClass('complete');
	    	}
	    	node.ownerTree.selModel.select(node);
	    }
	}
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.Grid = Ext.extend(Ext.grid.GridPanel, {
	mode : null // wallpapers or themes
	, ownerModule : null
	
	, constructor : function(config){
		// constructor pre-processing
		config = config || {};
		
		this.ownerModule = config.ownerModule;
		this.mode = config.mode;
	    
	    var reader = new Ext.data.JsonReader({
	    	fields: ['group', 'id', 'name', 'thumbnail', 'file']
			, id: 'id'
			, root: this.mode //'wallpapers'
		});
	    
	    var largeIcons = new Ext.Template(
			'<div class="x-grid3-row ux-explorerview-item ux-explorerview-large-item" unselectable="on">'+
			'<table class="ux-explorerview-icon" cellpadding="0" cellspacing="0">'+
			'<tr><td align="center"><img src="{thumbnail}"></td></tr></table>'+
			'<div class="ux-explorerview-text"><div class="x-grid3-cell x-grid3-td-name" unselectable="on">{name}</div></div></div>'
		);
    
		// this config
		Ext.applyIf(config, {
			columns: [
				{header: 'Group', width: 40, sortable: true, dataIndex: 'group'}
				, {header: 'Name', sortable: true, dataIndex: 'name'}
			]
			, enableDragDrop: false
			, hideHeaders: true
			, sm: new Ext.grid.RowSelectionModel({
				listeners: {
					'rowselect': { fn: this.onRowSelect, scope: this }
				}
				, singleSelect: true
			})
			, store: new Ext.data.GroupingStore({
				baseParams: { 
					method: (this.mode === 'themes' ? 'viewThemes' : 'viewWallpapers')
					, moduleId: this.ownerModule.id
				}
				, groupField: 'group'
				, listeners: {
					'load': { fn: this.selectRecord, scope: this }
				}
				, reader: reader
				, sortInfo: {field: 'name', direction: 'ASC'}
				, url: config.ownerModule.app.connection
				
			})
         , view: new Ext.ux.grid.ExplorerView({
			//, view: new Ext.ux.grid.GroupingExplorerView({
				rowTemplate: largeIcons
				, forceFit: true
				//, groupTextTpl: '{text} ({[values.rs.length]})'
				//, showGroupName: false
			})
		});
		
		QoDesk.QoPreferences.Grid.superclass.constructor.apply(this, [config]);
		// constructor post-processing
		
		this.desktop = this.ownerModule.app.getDesktop();
	}
	
	// added methods
	
	, onRowSelect : function(sm, index, record){
		var r = record;
		var d = r.data;
		var id;
      var desktop = this.ownerModule.app.getDesktop();
		
		if(this.mode === 'themes'){
			id = desktop.getAppearance().theme.id;
		}else{
			id = desktop.getBackground().wallpaper.id;
		}
		
		if(parseInt(id) !== parseInt(r.id)){
			if(r && r.id && d.name && d.file){
				config = {
					id: r.id
					, name: d.name
					, file: d.file
				};
				
				if(this.mode === 'themes'){
					this.desktop.setTheme(config);
				}else{
					this.desktop.setWallpaper(config);
				}
			}
		}
	}
	
	, selectRecord : function(){
		var id;
		var desktop = this.ownerModule.app.getDesktop();

		if(this.mode === 'themes'){
			id = desktop.getAppearance().theme.id;
		}else{
			id = desktop.getBackground().wallpaper.id;
		}
		
		this.selModel.selectRecords([this.store.getById(id)]);
	}
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.Nav = Ext.extend(Ext.Panel, {
   constructor : function(config){
      // constructor pre-processing
      config = config || {};
		
		this.ownerModule = config.ownerModule;
		
      this.actions = {
         'viewShortcuts' : function(ownerModule){
            ownerModule.viewCard('pref-win-card-6');
         }
         , 'viewAutoRun' : function(ownerModule){
            ownerModule.viewCard('pref-win-card-5');
         }
         , 'viewQuickstart' : function(ownerModule){
            ownerModule.viewCard('pref-win-card-2');
         }
         , 'viewAppearance' : function(ownerModule){
            ownerModule.viewCard('pref-win-card-3');
         }
         , 'viewWallpapers' : function(ownerModule){
            ownerModule.viewCard('pref-win-card-4');
         }
      };
		
      // this config
      Ext.applyIf(config, {
         autoScroll: true
         , bodyStyle: 'padding:15px'
         , border: false
      });
		
      QoDesk.QoPreferences.Nav.superclass.constructor.apply(this, [config]);
      // constructor post-processing
   }
	
   // overrides
	
   , afterRender : function(){
   	var tpl = new Ext.XTemplate(
         '<ul class="pref-nav-list">'
         , '<tpl for=".">'
            , '<li><div>'
               , '<div class="prev-link-item-icon"><img src="'+Ext.BLANK_IMAGE_URL+'" class="{cls}"/></div>'
               , '<div class="prev-link-item-txt"><a id="{id}" href="#">{text}</a><br />{description}</div>'
               , '<div class="x-clear"></div>'
            , '</div></li>'
         , '</tpl>'
         , '</ul>'
   	);
   	tpl.overwrite(this.body, this.ownerModule.locale.data.nav);
   	
      this.body.on({
         'mousedown': {
            fn: this.doAction
            , scope: this
            , delegate: 'a'
         }
         , 'click': {
            fn: Ext.emptyFn
            , scope: null
            , delegate: 'a'
            , preventDefault: true
         }
      });
		
      QoDesk.QoPreferences.Nav.superclass.afterRender.call(this); // do sizing calcs last
   }

   // added methods

   , doAction : function(e, t){
      e.stopEvent();
      this.actions[t.id](this.ownerModule);  // pass ownerModule for scope
   }
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.QuickStart = Ext.extend(Ext.Panel, {
   constructor : function(config){
      // constructor pre-processing
      config = config || {};

      this.ownerModule = config.ownerModule;

      // this config
      Ext.applyIf(config, {
         border: false
         , buttons: [
            {
               disabled: this.ownerModule.app.isAllowedTo('saveQuickstart', this.ownerModule.id) ? false : true
               , handler: onSave
               , scope: this
               , text: 'Save'
            }
            , {
               handler: onClose
               , scope: this
               , text: 'Close'
            }
         ]
         , cls: 'pref-card'
         , items: [
            {
               bodyStyle: 'padding:0 5px 0 0'
               , border: false
               , html: this.ownerModule.locale.html.quickstart
               , region: 'center'
               , xtype: 'panel'
            }
				, new QoDesk.QoPreferences.CheckTree({
               launcherKey: 'quickstart',
               listeners: {
                  'checkchange': { fn: onCheckChange, scope: this }
               }
               , ownerModule: config.ownerModule
               , region: 'west'
            })
         ]
         , layout: 'border'
         , title: this.ownerModule.locale.title.quickstart
      });

      QoDesk.QoPreferences.QuickStart.superclass.constructor.apply(this, [config]);
      // constructor post-processing

      function onClose(){
         this.ownerModule.win.close();
      }

      function onSave(){
         this.buttons[0].disable();
         this.ownerModule.save({
            method: 'saveQuickstart'
            , callback: function(){
               this.buttons[0].enable();
            }
            , callbackScope: this
            , ids: Ext.encode(this.ownerModule.app.getDesktop().getLauncher('quickstart'))
         });
      }

      function onCheckChange(node, checked){
         if(node.leaf && node.id){
            if(checked){
               this.ownerModule.app.desktop.addQuickStartButton(node.id, true);
            }else{
               this.ownerModule.app.desktop.removeQuickStartButton(node.id, true);
            }
         }
      }
   }
});/*
 * qWikiOffice Desktop 1.0
 * Copyright(c) 2007-2008, Integrated Technologies, Inc.
 * licensing@qwikioffice.com
 * 
 * http://www.qwikioffice.com/license
 */

QoDesk.QoPreferences.Shortcuts = Ext.extend(Ext.Panel, {
   constructor : function(config){
      // constructor pre-processing
      config = config || {};

      this.ownerModule = config.ownerModule;

      // this config
      Ext.applyIf(config, {
         border: false
         , buttons: [
            {
               disabled: this.ownerModule.app.isAllowedTo('saveShortcut', this.ownerModule.id) ? false : true
               , handler: onSave
               , scope: this
               , text: this.ownerModule.locale.button.save.text
            }
            , {
               handler: onClose
               , scope: this
               , text: this.ownerModule.locale.button.close.text
            }
         ]
         , cls: 'pref-card'
         , items: [
            {
               bodyStyle: 'padding:0 5px 0 0'
               , border: false
               , html: 'Selected applications will be available as a desktop Shortcut.  Don\'t forget to click the \'Save\' button.'
               , region: 'center'
               , xtype: 'panel'
            }
            , new QoDesk.QoPreferences.CheckTree({
               launcherKey: 'shortcut',
               listeners: {
                  'checkchange': { fn: onCheckChange, scope: this }
               }
               , ownerModule: config.ownerModule
               , region: 'west'
            })
         ]
         , layout: 'border'
         , title: this.ownerModule.locale.title.shortcuts
      });

      QoDesk.QoPreferences.Shortcuts.superclass.constructor.apply(this, [config]);
      // constructor post-processing

      function onClose(){
         this.ownerModule.win.close();
      }

      function onSave(){
         this.buttons[0].disable();
         this.ownerModule.save({
            method: 'saveShortcut'
            , callback: function(){
               this.buttons[0].enable();
            }
            , callbackScope: this
            , ids: Ext.encode(this.ownerModule.app.getDesktop().getLauncher('shortcut'))
         });
      }

      function onCheckChange(node, checked){
         if(node.leaf && node.id){
            if(checked){
               this.ownerModule.app.getDesktop().addShortcut(node.id, true);
            }else{
               this.ownerModule.app.getDesktop().removeShortcut(node.id, true);
            }
         }
      }
   }
});QoDesk.QoPreferences.Locale = {
   "launcher": {
   	"text": "QO Preferences"
      , "tooltip": "<b>QO Preferences</b><br />Allows you to modify your desktop"
   }
   , "button": {
   	"back": {
   		"text": "Back"
   	}
   	, "backgroundColor": {
   		"text": "Background Color"
   	}
   	, "close": {
         "text": "Close"
   	}
   	, "fontColor": {
         "text": "Font Color"
      }

   	, "next": {
   		"text": "Next"
   	}
   	, "save": {
   		"text": "Save"
   	}
   }
   , "connection": {
   	"lost": {
	      "msg": "Lost connection to server."
	      , "title": "Error"
	   }
   }
   , "error": {
   	"msg": "Errors encountered on the server."
   	, "title": "Error"
   }
   , "data": {
   	"nav": [
         {
         	"cls": "icon-pref-shortcut"
         	, "id": "viewShortcuts"
         	, "text": "Shortcuts"
         	, "description": "Choose which applications appear in your shortcuts"
         }
         , {
            "cls": "icon-pref-autorun"
            , "id": "viewAutoRun"
            , "text": "Auto Run"
            , "description": "Choose which applications open automatically once logged in"
         }
         , {
            "cls": "icon-pref-quickstart"
            , "id": "viewQuickstart"
            , "text": "Quick Start"
            , "description": "Choose which applications appear in your Quick Start panel"
         }
         , {
            "cls": "icon-pref-appearance"
            , "id": "viewAppearance"
            , "text": "Window Color and Appearance"
            , "description": "Fine tune window color and style of your windows"
         }
         , {
            "cls": "icon-pref-wallpaper"
            , "id": "viewWallpapers"
            , "text": "Desktop Background"
            , "description": "Choose from available wallpapers or colors to decorate you desktop"
         }
   	]
   }
   , "html": {
   	"autorun": "Selected applications will load and run automatically when you sign in.  Don\"t forget to click the \"Save\" button.<br /><br /><b>Note:</b><br />The more applications selected, the longer startup will take."
      , "quickstart": "Selected applications will be available from the Quick Start panel.  Don\"t forget to click the \"Save\" button."
   }
   , "label": {
      "backgroundColor": "Choose a background color"
      , "fontColor": "Choose a font color"
      , "transparency": "Taskbar Transparency"
      , "wallpaperPosition": "How should the wallpaper be positioned?"
   }
   , "notification": {
   	"saved": {
	      "msg": "Save complete."
	      , "title": "Finished"
	   }
	   , "saving": {
	   	"msg": "Saving your data..."
	   	, "title": "Please wait"
	   }
   }
   , "title": {
      "appearance": "Window Color And Appearance"
      , "autorun": "Auto Run"
      , "background": "Desktop Background"
      , "quickstart": "Quick Start"
      , "shortcuts": "Shortcuts"
      , "window": "QO Preferences"
   }
};